#include <iostream>
#include "boost/beast.hpp"

#include <chrono>
#include <ctime>
#include <cstdlib>
#include <memory>
#include <string>
#include <json/json.h>


// namespace beast = boost::beast;
// namespace http = beast::http;
namespace net = boost::asio;
using tcp = boost::asio::ip::tcp;

namespace my_program_state
{
    std::size_t request_count(){
        static std::size_t count = 0;
        return ++count;
    }
    std::time_t now(){
        return std::time(0);
    }
}

class HttpConnection : public std::enable_shared_from_this<HttpConnection>
{
public:
    HttpConnection(tcp::socket&& socket)
        : socket_(std::move(socket))
    {
    }

    void Start()
    {
        ReadRequest();
        CheckDeadline();//超时检测
    }

private:
    tcp::socket socket_;
    boost::beast::flat_buffer buffer_{8192};
    //dynamic_body是一个动态请求的包体，可以接收各种请求。 其他body类型：string_body, empty_body, file_body, vector_body
    boost::beast::http::request<boost::beast::http::dynamic_body> request_;
    boost::beast::http::response<boost::beast::http::dynamic_body> response_;
    //定时器类型，用于检测请求是否超时
    boost::asio::steady_timer deadline_{
        socket_.get_executor(),//获取socket的执行器，用于绑定定时器到socket的IO线程
        std::chrono::seconds(60)
    };
private:
    void ReadRequest()
    {
        auto self(shared_from_this());
        boost::beast::http::async_read(socket_,buffer_,request_,[self](boost::beast::error_code ec, ::std::size_t bytes_transferred){
            //忽略未使用的参数
            boost::ignore_unused(bytes_transferred);

            if(ec)
            {
                std::cout<<"ReadRequest error value = "<<ec.value()<<" message = "<<ec.message()<<std::endl;
                return;
            }
            //处理请求
            self->ProcessRequest();
            //发送响应
            self->WriteResponse();
        });
    }

    void CheckDeadline()
    {
        auto self(shared_from_this());
        deadline_.async_wait([self](const boost::system::error_code& ec){
            if(ec)
            {
                std::cout<<"CheckDeadline error value = "<<ec.value()<<" message = "<<ec.message()<<std::endl;
            }
            self->socket_.close();
        });
    }

    void ProcessRequest()
    {
        //设定起始行的http版本号
        response_.version(request_.version());

        response_.keep_alive(request_.keep_alive());
        //请求方法
        switch (request_.method())
        {
        case boost::beast::http::verb::get:
            //设定起始行的http状态码
            response_.result(boost::beast::http::status::ok);
            response_.set(boost::beast::http::field::server,"beastHttpServerGet");
            //添加一个自定义首部字段
            response_.set("X-HSL","this is hsl's demo project");
            create_response();
            break;
        
        case boost::beast::http::verb::post:
            response_.result(boost::beast::http::status::ok);
            response_.set(boost::beast::http::field::server,"beastHttpServerPost");
            create_post_response();
            break;
        default:
            response_.result(boost::beast::http::status::bad_request);
            response_.set(boost::beast::http::field::content_type,"text/plain");
            //向响应体中写入错误信息
            boost::beast::ostream(response_.body()) << "Invalid request method"<<
            std::string(request_.method_string());
            break;
        }
    }

    void create_response()
    {
        if(request_.target()=="/count")
        {
            response_.set(boost::beast::http::field::content_type,"text/html");
            boost::beast::ostream(response_.body())<<"<html lang=\"zh-CN\">\n"<<
            "<head><title>Request Count</title></head>\n"<<
            "<body><h1>Request Count</h1>"<<
            "<p>Total requests: "<<my_program_state::request_count()<<"</p>"<<
            "</body></html>\n";
        }
        else if(request_.target()=="/time")
        {
            response_.set(boost::beast::http::field::content_type,"text/html");
            boost::beast::ostream(response_.body())<<"<html lang=\"zh-CN\">\n"<<
                "<head><title>Current Time</title></head>"<<
                "<body><h1>Current time</h1>"<<
                "<p>current time: "<<my_program_state::now()<<"</p>"<<
                "</body></html>\n";
        }
        else
        {
            response_.result(boost::beast::http::status::not_found);
            response_.set(boost::beast::http::field::content_type,"text/plain");
            //向响应体中写入错误信息
            boost::beast::ostream(response_.body()) << "404 Not Found"<<
            std::string(request_.target());
        }
    }

    void create_post_response()
    {
        if (request_.target()=="/email")
        {
            auto& body =  request_.body();
            //拿到body中的数据
            auto body_str = boost::beast::buffers_to_string(body.data());
            std::cout<<"receive body is "<<body_str<<std::endl;
            response_.set(boost::beast::http::field::content_type,"application/json");
            Json::Value root;//存放回应给客户端的json数据
            Json::Value src_root;//存放解析body_str后的json数据
            Json::Reader reader;
            bool parse_success = reader.parse(body_str,src_root);
            if(!parse_success)
            {
                std::cout<<"Failed to parse client json data"<<std::endl;
                root["error"]=1001;
                std::string jsonstr = root.toStyledString();
                boost::beast::ostream(response_.body())<<jsonstr;
                return;
            }
            root["error"]=0;
            std::string client_email = src_root["email"].asString();
            std::cout<<"client email is "<<client_email<<std::endl;

            root["email"] = client_email;
            root["msg"]="server receive success";
            boost::beast::ostream(response_.body())<<root.toStyledString();
        }
        else
        {
            response_.result(boost::beast::http::status::not_found);
            response_.set(boost::beast::http::field::content_type,"text/plain");
            std::string not_found_msg = "404 Not Found" + std::string(request_.target());
            boost::beast::ostream(response_.body())<<not_found_msg;
            
        }
        

    }




    void WriteResponse()
    {
        auto self(shared_from_this());
        //设定响应体的大小
        response_.content_length(response_.body().size());
        
        boost::beast::http::async_write(socket_,response_,[self](const ::boost::beast::error_code &ec, ::std::size_t bytes_transferred){
            if(ec)
            {
                std::cout<<"WriteResponse error value = "<<ec.value()<<" message = "<<ec.message()<<std::endl;
                return;
            }
            //关闭socket的发送端，为什么不用close？
                //因为主动发起close的一方会产生一个等待，这个等待时间是2MSL（ESTABLISH_WAIT）
            self->socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_send);

            //关闭定时器
            self->deadline_.cancel();

        });
        return;
    }
};

void HttpServer(boost::asio::ip::tcp::acceptor& acceptor,boost::asio::ip::tcp::socket& socket)
{
    acceptor.async_accept(socket,[&acceptor,&socket](const boost::system::error_code& ec){
        if(ec)
        {
            std::cout<<"HttpServer error value = "<<ec.value()<<" message = "<<ec.message()<<std::endl;
            return;
        }
        std::make_shared<HttpConnection>(std::move(socket))->Start();
        HttpServer(acceptor,socket);
    });
}

int main()
{

    boost::asio::io_context io_context;
    //填写ip地址和端口号
    boost::asio::ip::tcp::endpoint endpoint(boost::asio::ip::address::from_string("0.0.0.0"),8888);
    boost::asio::ip::tcp::acceptor acceptor(io_context,endpoint);
    boost::asio::ip::tcp::socket socket(io_context);

    HttpServer(acceptor,socket);
    io_context.run();
    return 0;
}


